class Promise {
  // 构造方法
  constructor(excutor) {
    // 添加属性
    this.PromiseState = 'pending'
    this.PromiseResault = null
    // 声明一个对象
    this.callbacks = []
    // 保存实例对象的this值
    const _this = this
    // resolve函数
    function resolve(data) {
      // 判断状态-promise状态只允许修改一次
      if (_this.PromiseState !== 'pending') return
      // 1、修改对象状态（promiseState）
      _this.PromiseState = 'fulfilled'
      // 2、设置对象结果值（promiseResault）
      _this.PromiseResault = data
      // 调用成功的回调函数
      setTimeout(() => {
        _this.callbacks.forEach((item) => {
          item.onResolved(data)
        })
      })
    }
    // reject函数
    function reject(data) {
      // 判断状态-promise状态只允许修改一次
      if (_this.PromiseState !== 'pending') return
      // 1、修改对象状态（promiseState）
      _this.PromiseState = 'rejected'
      // 2、设置对象结果值（promiseResault）
      _this.PromiseResault = data
      setTimeout(() => {
        _this.callbacks.forEach((item) => {
          item.onRejected(data)
        })
      })
    }
    // 使用try-catch实现throw逻辑
    try {
      // 不同调用执行器函数
      excutor(resolve, reject)
    } catch (error) {
      reject(error)
    }
  }
  // then方法
  then(onResolved, onRejected) {
    const _this = this
    // 判断回调函数参数
    if (typeof onRejected !== 'function') {
      onRejected = (reason) => {
        throw reason
      }
    }
    if (typeof onResolved !== 'function') {
      onResolved = (value) => value
    }
    return new Promise((resolve, reject) => {
      // 封装回调函数
      function callback(type) {
        try {
          // 获取回调函数执行结果
          let result = type(_this.PromiseResault)
          // 判断
          if (result instanceof Promise) {
            // 如果是Promise类型对象
            result.then(
              (v) => {
                resolve(v)
              },
              (r) => {
                reject(r)
              }
            )
          } else {
            // 结果的对象状态为成功
            resolve(result)
          }
        } catch (error) {
          reject(error)
        }
      }
      // 调用回调函数
      if (this.PromiseState === 'fulfilled') {
        setTimeout(() => {
          callback(onResolved)
        })
      }
      if (this.PromiseState === 'rejected') {
        setTimeout(() => {
          callback(onRejected)
        })
      }
      // 判断pending状态
      if (this.PromiseState === 'pending') {
        // 保存回调函数
        this.callbacks.push({
          onResolved: function () {
            callback(onResolved)
          },
          onRejected: function () {
            callback(onRejected)
          },
        })
      }
    })
  }
  // catch方法
  catch(onRejected) {
    return this.then(undefined, onRejected)
  }
  // resolve方法
  static resolve(value) {
    // 返回promise对象
    return new Promise((resolve, reject) => {
      if (value instanceof Promise) {
        value.then(
          (v) => {
            resolve(v)
          },
          (r) => {
            reject(r)
          }
        )
      } else {
        resolve(value)
      }
    })
  }
  // reject方法
  static reject(reason) {
    return new Promise((resolve, reject) => {
      reject(reason)
    })
  }
  // 添加all方法
  static all(promises) {
    // 返回结果
    return new Promise((resolve, reject) => {
      // 声明变量
      let count = 0
      let arr = []
      // 遍历
      for (let i = 0; i < promises.length; i++) {
        promises[i].then(
          (v) => {
            // 此处状态为成功
            // 每个promise都成功再执行resolve
            count++
            // 将当前promise成功的结果存放到arr中
            arr[i] = v
            if (count === promises.length) {
              // 修改状态
              resolve(arr)
            }
          },
          (r) => {
            reject(r)
          }
        )
      }
    })
  }
  // race方法
  static race(promises) {
    return new Promise((resolve, reject) => {
      for (let i = 0; i < promises.length; i++) {
        promises[i].then(
          (v) => {
            // 修改返回对象的状态-成功
            resolve(v)
          },
          (r) => {
            // 修改返回对象的状态-失败
            reject(r)
          }
        )
      }
    })
  }
}
